#include "Portal.h"
#include "Cliente.h"
#include "Consulta.h"
#include "GestorArchivoConfiguracion.h"
#include "Cliente.h"
#include "Atributoconsulta.h"
#include "Respuesta.h"
#include "Util.h"
#include <sstream>

Portal::Portal(unsigned int filas, unsigned int numTabla):
	Gtk::Table(filas, 2, false), numeroTabla(numTabla) {
	labelFiltros.set_label("Filtros: ");
	set_border_width(5);
	filaActual = 0;
	cantCombos = 0;
}

Portal::~Portal() {}

void Portal::setNumeroConsulta(unsigned int numero) {
	numeroConsulta = numero;
}

void Portal::setGestorConfiguracion(GestorArchivoConfiguracion* gestor) {
	gestorConfig = gestor;
}
void Portal::setCliente(Cliente* cli) {
	cliente = cli;
}

void Portal::setValoresFiltro(std::vector<std::string>& values) {
	Gtk::Label *etiqueta;

	std::vector<std::string>::iterator it = values.begin();
	for(; it != values.end(); it++) {
		filtros.push_back(*it);
		etiqueta = Gtk::manage(new Gtk::Label());
		etiqueta->set_text(*it);
		attach(*etiqueta, 1, 2, filaActual, filaActual + 1);// + 1);
		filaActual++;
	}
	attach(labelFiltros, 0, 1, 0, 1);
}


void parsearLineaRespuestaCombo(std::string& linea, std::string& nombre, std::vector<std::string>& valores) {
	unsigned int pos = 0;
	pos = linea.find(Util::PIPE, 0);
	nombre = linea.substr(0, pos);
	pos++;
	linea[linea.size() - 1] = 0;
	while((linea.find(Util::PIPE, pos) != std::string::npos)) {
		std::string valor = linea.substr(pos, linea.find(Util::PIPE, pos + 1) - pos);
		pos = linea.find(Util::PIPE, pos + 1);
		if(pos != std::string::npos)
			pos++;
		valores.push_back(valor);
	}
	std::string ultimoValor = linea.substr(pos, std::string::npos - pos);
	valores.push_back(ultimoValor);
}


void Portal::parsearLineasRespuesta(std::string& linea, std::vector<Atributo_consulta>& atribs) {
	unsigned int pos = 0;
	while(linea.find(Util::PIPE, pos) != std::string::npos) {
		std::string atributo = linea.substr(pos, linea.find(Util::PIPE, pos + 1) - pos);
		std::stringstream ss(atributo);
		char tipo;
		std::string nombre;
		ss >> tipo;
		ss.ignore();
		unsigned int pos_obtenida;
		ss >> pos_obtenida;
		std::map<std::string, Gtk::ComboBoxText*>::iterator it;
		for(it = mapaInputs.begin(); it != mapaInputs.end(); ++it) {
			std::string sAux = (*it).first;
			unsigned int posicion = gestorConfig->getPosicionTabla(numeroTabla, sAux);
			if(posicion == pos_obtenida)
				nombre = (*it).first;
		}
		pos = linea.find(Util::PIPE, pos + 1);
		if(pos != std::string::npos)
			pos++;
		Atributo_consulta atrib_cons(nombre, tipo, pos_obtenida, 'a');
		atribs.push_back(atrib_cons);
	}
}



void Portal::setRespuesta(Respuesta* respuesta) {
	// AQUI RECIEB LA RESPUESTA
	/*
	 * DEBE EXTRAER EL VALOR DE LOS STRING Y METERLOS AL COMBO
	 * ahora PARA SABER A QUE COMBO PERTENECE HAY 2 MANERAS:
	 *
	 * 1-A TRAVES DEL NOOMBRE DEL COMBO(INPUT)
	 * USO UN MAP:
	 * 	std::map<std::string, Gtk::ComboBoxText*> mapaInputs;	// la clave es el nombre del input
	 *
	 * EL NOMBREDEL INPUT ME DA LA REFERENCIA DEL COMBO
	 * ASI Q EL NOMBRE DEBE SALIR DE LA RESPUESTA, CON ESO OBTIENENN EL INPUT DE mapaInputs
	 *
	 * 2- SI LA RESPUESTA ENVIA LA POSICION DE  LA COLUMNA SE PUEDE
	 * USAR EL GESTOR Y OBTNER LA POSICION DE TODOS LOS INPUTS, LUEGO COMPARAR HASTA Q COINCIDA
	 * CON LA POSICION DE LA RESPUESTA.
	 *
	 * ---SE USARA UN ITERADOR DEL MAP.......
	 * unsigned int posicion = gestorConfig->getPosicionTabla(numeroTabla, nombre);
	 * DONDE nombre ES LA CLAVE DEL MAP(mapaInputs)
	 *
	 * ******************
	 * DESPUESDE OBTENER EL COMBObOST PARCEAN LA RESPUESTA YMETEN LOS VALORES AL COMBO
	 * PARA METER UN STRING SE HACE:
	 *
	 * combo->append_text("soy un string");
	 *
	 *
	 */

	if(respuesta->getTipo() != 'C') {
		std::cout << respuesta->getTipo() << std::endl;
		throw("NO ES UNA RESPUESTA DE UN COMBO");
	}
	std::list<std::string>* listaLineas = respuesta->getLista();
	std::list<std::string>::iterator it;
	for(it = listaLineas->begin(); it != listaLineas->end(); ++it) {
		std::string nombre;
		std::vector<std::string> atribs;
		parsearLineaRespuestaCombo(*it, nombre, atribs);
		std::vector<std::string>::iterator it;

		///////////////////
		std::map<std::string, Gtk::ComboBoxText*>::iterator it2;
		for(it2 = mapaInputs.begin(); it2 != mapaInputs.end(); ++it2) {
			std::cout << (*it2).first << std::endl;
		}
		////////////////////

		for(it = atribs.begin(); it != atribs.end(); ++it) {
			mapaInputs[nombre]->append_text(*it);
		}
	}
	delete respuesta;
}
void Portal::setInputs(std::string& nombreInput, std::vector<std::string>& values) {
	Gtk::ComboBoxText* combo = Gtk::manage(new Gtk::ComboBoxText);
	Gtk::Label* etiqueta = Gtk::manage(new Gtk::Label(nombreInput));

	combo->set_size_request(100,30);

	mapaInputs[nombreInput] = combo;
	attach(*etiqueta, 0, 1, filaActual, filaActual + 1);
	attach(*combo, 1, 2, filaActual, filaActual + 1);
	filaActual++;

	combo->signal_changed().connect(sigc::bind(sigc::mem_fun(*this,&Portal::on_cambios_comboBox), combo));
	cantCombos++;
}

void Portal::on_cambios_comboBox(Gtk::ComboBoxText* comboSeleccionado) {
	std::vector<Gtk::ComboBoxText*>::iterator it = combos.begin();

	// solo si no esta dentro se agrega
	bool encontrado = false;
	for(; it != combos.end(); it++) {
		if(*it == comboSeleccionado) {
			encontrado = true;
			break;
		}
	}
	if(!encontrado)
		combos.push_back(comboSeleccionado);

	// si la cantidad de combos seleccionados es igual a la cantidad de combos, se hizo una consulta
	if(cantCombos == combos.size()) {
	//	std::cout<<"consulta enviada"<<std::endl;

		std::string nombre;	// sera el id_columna, ejemplo vendedor
		std::string valor;	// sera el valor de id_columna, ejemplo manuel
		Consulta* consulta = NULL;
		Atributo_consulta *atributo = NULL;
		unsigned int posicion;
		char tipo;

		consulta = new Consulta(0 , numeroTabla, numeroConsulta);	// SUPONGO Q LOS PARAMETROS USADOSSON CORRECTOS
		// SOBRE TODOO EL NUMERO DE CONSULTA, Q SIN ESO NADA FUNCIONA

		std::vector<std::string>::iterator itf = filtros.begin();
			for(; itf != filtros.end(); itf++) {
				obtenerValoresFiltro(*itf, nombre, valor);

				posicion = gestorConfig->getPosicionTabla(numeroTabla, nombre);
				tipo = Util::DIMENSION;
				if(gestorConfig->esHecho(numeroTabla, nombre))
					tipo = Util::HECHO;

				////////////////////////////
				std::cout << "valor" << valor << " tipo " << tipo << " posicion " << posicion << std::endl;
				/////////////////////////////

				atributo = new Atributo_consulta(valor, tipo, posicion, 'a');
				consulta->insertarAtributo(atributo);
			}

			std::map<std::string, Gtk::ComboBoxText*>::iterator iter= mapaInputs.begin();
			// mapa::: clave: nombreInput y del ComboBOxtext sacar el seleccionado

				for(; iter != mapaInputs.end(); iter++) {
					valor = (iter->second)->get_active_text();
					nombre = iter->first;

					posicion = gestorConfig->getPosicionTabla(numeroTabla, nombre);
					tipo = Util::DIMENSION;
					if(gestorConfig->esHecho(numeroTabla, nombre)) {
						tipo = Util::HECHO;
						atributo = new Atributo_consulta(nombre ,tipo, posicion, valor[0]);

					} else { //////////////////// ACA HICE CAMBIOS /////////////////

						atributo = new Atributo_consulta(valor, tipo, posicion, valor[0]);
					}   //////////////// FIN ACA HICE CAMBIOS //////////////////////
					consulta->insertarAtributo(atributo);
				}
				std::cout << consulta->serializar() << std::endl;
		cliente->pushConsulta(consulta);

		// limpio combos para que sea necesario seleccionar nuevamente todos los combos
		//combos.erase(combos.begin(), combos.end());
	}
}

void Portal::obtenerValoresFiltro(const std::string& origen, std::string& id_columna, std::string& valor_columna) {
	/*
	 * origen = "vendedor: marcos"
	 *
	 * un filtro es:
	 * vendedor: marcos
	 *
	 * debo parsear y devolver en id_columna: vendedor
	 * y en valo_columna: marcos
	 */
	unsigned int pos = origen.find(Util::DOSPUNTOS, 0);
	id_columna = origen.substr(0, pos);
	valor_columna = origen.substr(pos + 2, origen.size() - pos);
}

void Portal::cargarCombos() {
	std::string nombre;	// sera el id_columna, ejemplo vendedor
	std::string valor;	// sera el valor de id_columna, ejemplo manuel

	Consulta* consulta = new Consulta(0, numeroTabla, numeroConsulta);

	Atributo_consulta *atributo = NULL;
	unsigned int posicion;
	char tipo;

	std::map<std::string, Gtk::ComboBoxText*>::iterator iter= mapaInputs.begin();

	for(; iter != mapaInputs.end(); iter++) {
		nombre = iter->first;
		posicion = gestorConfig->getPosicionTabla(numeroTabla, nombre);
		std::cout << posicion << std::endl;
		std::cout << mapaInputs.size() << std::endl;
		tipo = Util::DIMENSION;
		if(gestorConfig->esHecho(numeroTabla, nombre)) {
			tipo = Util::HECHO;
			mapaInputs[nombre]->append_text(Util::SMAX);
			mapaInputs[nombre]->append_text(Util::SMIN);
			mapaInputs[nombre]->append_text(Util::SSUM);
			mapaInputs[nombre]->append_text(Util::SCOUNT);
			mapaInputs[nombre]->append_text(Util::SNONE);
			mapaInputs[nombre]->append_text(Util::SAVG);
		} else {
			atributo = new Atributo_consulta("COLUMNA", tipo, posicion, 'a');
			consulta->insertarAtributo(atributo);
			cliente->pushConsulta(consulta);
		}
	}
}








